package com.seeyon.apps.lzmzj.kit;

import com.seeyon.cap4.form.bean.*;
import com.seeyon.cap4.form.modules.engin.base.formData.CAP4FormDataManager;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.ModuleType;
import com.seeyon.ctp.common.authenticate.domain.User;
import com.seeyon.ctp.common.content.mainbody.CtpContentAllBean;
import com.seeyon.ctp.common.content.mainbody.MainbodyService;
import com.seeyon.ctp.common.content.mainbody.MainbodyStatus;
import com.seeyon.ctp.common.content.mainbody.MainbodyType;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.filemanager.dao.AttachmentDAO;
import com.seeyon.ctp.common.filemanager.manager.FileManager;
import com.seeyon.ctp.common.log.CtpLogFactory;
import com.seeyon.ctp.common.po.content.CtpContentAll;
import com.seeyon.ctp.common.po.filemanager.Attachment;
import com.seeyon.ctp.common.po.filemanager.V3XFile;
import com.seeyon.ctp.util.DateUtil;
import com.seeyon.ctp.util.UUIDLong;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;

import java.sql.Timestamp;
import java.util.Map;

public class FormCap4Kit {

    private static final Log log = CtpLogFactory.getLog(FormCap4Kit.class);

    private static CAP4FormDataManager cap4FormDataManager = (CAP4FormDataManager) AppContext.getBean("cap4FormDataManager");
    private static FileManager fileManager = (FileManager) AppContext.getBean("fileManager");
    private static AttachmentDAO attachmentDAO = (AttachmentDAO) AppContext.getBean("attachmentDAO");

    /**
     * 添加无流程表单数据及附件信息。
     * 此方法用于处理无流程的表单数据的添加操作，包括表单主数据的插入或更新，
     * 以及表单正文内容的保存。如果当前用户存在，则使用当前用户ID，
     * 否则使用表单创建者ID作为操作人ID。
     *
     * @param formDataMasterBean 表单主数据对象，包含要插入或更新的表单主数据信息。
     * @param formBean           表单详细数据对象，包含表单的权限视图信息和正文内容等。
     */
    public static void addUnFlowFormDataCap4(FormDataMasterBean formDataMasterBean, FormBean formBean) {
        try {
            // 尝试获取当前操作用户
            User user = AppContext.getCurrentUser();
            // 初始化用户ID变量，并尝试从当前用户获取用户ID
            Long userId = null;
            if (user != null) {
                userId = user.getId();
            }
            // 如果当前用户ID为空，则使用表单创建者ID
            if (userId == null) {
                userId = formBean.getCreatorId();
            }
            // 获取表单的权限视图信息，用于后续的操作权限判断
            FormAuthViewBean formAuthViewBean = formBean.getNewFormAuthViewBeans().get(0);
            // 将权限视图ID转换为字符串格式
            String rightid = String.valueOf(formAuthViewBean.getId());

            // 先插入或更新表单主数据
            cap4FormDataManager.insertOrUpdateMasterData(formDataMasterBean);
            // 获取刚刚插入或更新的表单主数据的ID
            Long masterId = formDataMasterBean.getId();

            // 确定表单模块类型，用于后续的正文内容处理
            int moduleType = getModuleTypeCap4(formBean);
            // 获取主body服务实例，用于保存正文内容
            MainbodyService mainBodyService = MainbodyService.getInstance();
            // 根据模块类型和主数据ID获取表单的正文内容
            CtpContentAll ctpContentAll = mainBodyService.getContent(moduleType, masterId);
            // 对获取到的正文内容进行加工或更新，同时设置操作人ID和权限视图ID
            ctpContentAll = saveContentAllForFormCap4(ctpContentAll, masterId, userId, formBean, rightid);
            // 保存或更新加工后的正文内容
            mainBodyService.saveOrUpdateContentAll(ctpContentAll);
        } catch (Exception e) {
            // 捕获并记录操作中可能出现的异常
            log.error("新增无流程表单数据报错信息:", e);
        }
    }


    /**
     * 保存表单内容信息。
     * 该方法用于处理表单内容的保存逻辑，包括新内容的创建和已有内容的更新。
     *
     * @param ctpContentAll 当前的内容信息，如果为null，则表示需要创建新内容。
     * @param masterId      主数据ID，用于关联内容和主数据。
     * @param userid        修改人ID，用于记录内容的修改者。
     * @param formBean      表单bean，包含表单的绑定信息和模块类型。
     * @param rightId       权限ID，用于记录内容的权限信息。
     * @return 返回保存或更新后的表单内容信息。
     * @throws BusinessException 如果没有应用绑定，则抛出业务异常。
     */
    private static CtpContentAll saveContentAllForFormCap4(CtpContentAll ctpContentAll, long masterId, long userid, FormBean formBean, String rightId) throws BusinessException {
        // 获取当前时间戳，用于记录创建或修改时间。
        Timestamp timestamp = DateUtil.currentTimestamp();
        // 如果ctpContentAll不为空，则进行更新操作。
        if (ctpContentAll != null) {
            // 更新修改人ID和修改时间。
            ctpContentAll.setModifyId(userid);
            ctpContentAll.setModifyDate(timestamp);
            return ctpContentAll;
        }
        // 创建新内容。
        CtpContentAllBean content = new CtpContentAllBean();
        // 获取表单的绑定信息。
        FormBindBean bindBean = formBean.getBind();
        if (bindBean != null) {
            // 设置模块模板ID。
            content.setModuleTemplateId(bindBean.getId());
            // 获取绑定授权信息。
            Map<String, FormBindAuthBean> bindAuth = bindBean.getUnFlowTemplateMap();
            // 如果没有绑定授权信息，则抛出业务异常。
            if (CollectionUtils.isEmpty(bindAuth.values())) {
                throw new BusinessException("无应用绑定");
            }
            // 遍历绑定授权信息，设置内容的标题。
            for (FormBindAuthBean authBean : bindAuth.values()) {
                content.setTitle(authBean.getName());
            }
        }
        // 设置模块类型。
        content.setModuleType(getModuleTypeCap4(formBean));
        // 设置创建人ID和创建时间。
        content.setCreateId(userid);
        content.setCreateDate(timestamp);
        // 设置排序字段。
        content.setSort(0);
        // 设置内容的唯一ID。
        content.setId(UUIDLong.longUUID());
        // 设置内容的状态。
        content.setStatus(MainbodyStatus.STATUS_POST_SAVE);
        // 设置内容的类型。
        content.setContentType(Integer.valueOf(MainbodyType.FORM.getKey()));
        // 设置内容模板ID。
        content.setContentTemplateId(formBean.getId());
        // 设置内容数据ID。
        content.setContentDataId(masterId);
        // 设置模块ID。
        content.setModuleId(masterId);
        // 更新修改时间。
        content.setModifyDate(timestamp);
        // 更新修改人ID。
        content.setModifyId(userid);
        // 设置权限ID。
        content.setRightId(rightId);
        // 将内容bean转换为内容all对象并返回。
        return content.toContentAll();
    }


    /**
     * 根据表单类型获取模块类型常量值。
     * 此方法专门处理表单类型为6的情况，映射到相应的模块类型常量。
     * 如果表单类型不是6，则认为是无效的表单类型，抛出业务异常。
     *
     * @param formBean 表单bean对象，包含表单类型信息。
     * @return 返回模块类型常量的整型值。
     * @throws BusinessException 如果表单类型无效，则抛出业务异常。
     */
    private static int getModuleTypeCap4(FormBean formBean) throws BusinessException {
        /* 初始化模块类型为0，表示默认状态 */
        int moduleType = 0;
        /* 判断表单类型是否为6 */
        if (formBean.getFormType() == 6) {
            /* 如果是，則将模块类型设置为cap4UnflowForm对应的键值 */
            moduleType = ModuleType.cap4UnflowForm.getKey();
        }
        /* 如果模块类型仍然为0，说明表单类型不是6，视为无效表单类型 */
        if (moduleType == 0) {
            /* 记录日志警告无效的表单类型 */
            log.warn("无效表类型");
            /* 抛出业务异常，提示内容保存失败 */
            throw new BusinessException("内容保存失败");
        }
        /* 返回计算得到的模块类型 */
        return moduleType;
    }

    /**
     * 添加附件信息
     * <p>
     * * @param invoiceType 票据类型
     *
     * @param fileId        文件ID，用于从文件管理中获取文件信息
     * @param dataId        数据ID，表示附件所属的数据项
     * @param sub_reference 子引用ID，用于进一步细化附件的归属或分类
     */
    public static void addAttachment(Long fileId, Long dataId, Long sub_reference) {
        try {
            // 从文件管理中获取V3X文件对象
            V3XFile v3xFile = fileManager.getV3XFile(fileId);

            // 创建一个新的Attachment对象
            Attachment attachment = new Attachment();
            // 如果是新的附件，则设置其ID
            attachment.setIdIfNew();
            // 设置附件的类别为66，这里的66可能是预定义的附件类别代码
            attachment.setCategory(66);
            // 设置附件的创建日期
            attachment.setCreatedate(v3xFile.getCreateDate());
            // 设置附件的描述信息
            attachment.setDescription(v3xFile.getDescription());
            // 设置附件的文件名
            attachment.setFilename(v3xFile.getFilename());
            // 设置附件的文件URL，这里使用文件ID作为URL
            attachment.setFileUrl(v3xFile.getId());
            // 设置附件的引用ID，表示附件所属的数据项
            attachment.setReference(dataId);
            // 设置附件的子引用ID，用于进一步细化附件的归属或分类
            attachment.setSubReference(sub_reference);
            // 设置附件的类型
            attachment.setType(v3xFile.getType());
            // 设置附件的MIME类型
            attachment.setMimeType(v3xFile.getMimeType());
            // 设置附件的大小
            attachment.setSize(v3xFile.getSize());
            // 设置附件的排序字段，默认为1
            attachment.setSort(1);

            // 保存附件信息到数据库
            attachmentDAO.save(attachment);
        } catch (Exception e) {
            // 记录添加附件信息失败的日志
            log.error("添加附件信息失败:", e);
        }
    }

}
